#include"Server.h"
#include"Data.h"
#include"User.h"
#include"Auth.h"
#include"Util.h"

namespace aod {
    TableVideo* tbv = nullptr;  // 定义全局变量
    TableUser* tbu = nullptr;
    TableUserSession* tbus = nullptr;
    TableVideoLikes* tbvl = nullptr;
}

bool aod::Server::RunModule()
{
    //1、初始化数据管理模块 创建指定目录
    tbv = new TableVideo();
    tbu = new TableUser();
    tbus = new TableUserSession();
    tbvl = new TableVideoLikes();
    std::string www_root = WWWROOT;
    aod::FileUtil(www_root).CreateDirectory();
    std::string video_real_path = www_root + std::string(VIDEO_ROOT);
    aod::FileUtil(video_real_path).CreateDirectory();
    std::string image_real_path = www_root + std::string(IMAGE_ROOT);
    aod::FileUtil(image_real_path).CreateDirectory();
    
    //2、搭建http服务器，运行服务器
    //设置静态根目录
    _server.set_mount_point("/",www_root);
    //添加请求，映射接口
    //使用 Lambda 表达式注册回调
    _server.Post("/video", [this](const httplib::Request& req, httplib::Response& res) { 
        this->Insert(req, res); 
    });
    _server.Delete("/video/(\\d+)", [this](const httplib::Request& req, httplib::Response& res) { 
        this->Delete(req, res); 
    });
    _server.Put("/video/(\\d+)", [this](const httplib::Request& req, httplib::Response& res) { 
        this->Update(req, res); 
    });
    _server.Get("/video/(\\d+)", [this](const httplib::Request& req, httplib::Response& res) { 
        this->SelectOne(req, res); 
    });
    _server.Get("/video", [this](const httplib::Request& req, httplib::Response& res) { 
        this->SelectAll(req, res); 
    });
    
    // 用户管理API
    _server.Post("/user/register", [this](const httplib::Request& req, httplib::Response& res) { 
        this->UserRegister(req, res); 
    });
    _server.Post("/user/login", [this](const httplib::Request& req, httplib::Response& res) { 
        this->UserLogin(req, res); 
    });
    _server.Post("/user/logout", [this](const httplib::Request& req, httplib::Response& res) { 
        this->UserLogout(req, res); 
    });
    _server.Post("/user/session/refresh", [this](const httplib::Request& req, httplib::Response& res) { 
        this->UserRefreshSession(req, res); 
    });
    _server.Get("/user/(\\d+)", [this](const httplib::Request& req, httplib::Response& res) { 
        this->GetUserInfo(req, res); 
    });
    _server.Put("/user/(\\d+)", [this](const httplib::Request& req, httplib::Response& res) { 
        this->UpdateUserInfo(req, res); 
    });
    
    // 视频点赞API
    _server.Post("/video/(\\d+)/like", [this](const httplib::Request& req, httplib::Response& res) { 
        this->LikeVideo(req, res); 
    });
    _server.Get("/video/(\\d+)/like/status", [this](const httplib::Request& req, httplib::Response& res) { 
        this->GetVideoLikeStatus(req, res); 
    });
    
    //启动
    std::cout << "服务器启动，监听端口: " << _port << std::endl;
    _server.listen("0.0.0.0", _port);
    
    return true;
}

void aod::Server::Insert(const httplib::Request& req, httplib::Response& res) {
    std::cout << "调用Insert函数" << std::endl;
    // 1. 检查必需字段
    if (!req.has_file("name") || !req.has_file("info") || !req.has_file("video") || !req.has_file("image")) {
        res.status = 400;
        std::cout << req.has_file("name") << req.has_file("info") << req.has_file("video") << req.has_file("image") << std::endl;
        res.set_content(R"({"result":false,"reason":"缺少必需字段"})", "application/json");
        return;
    }

    // 2. 获取上传的文件数据
    auto name = req.get_file_value("name");
    auto info = req.get_file_value("info");
    auto video = req.get_file_value("video");
    auto image = req.get_file_value("image");

    // 3. 构建存储路径
    std::string www_root = WWWROOT;
    std::string video_path = www_root + VIDEO_ROOT + "/" + video.filename;
    std::string image_path = www_root + IMAGE_ROOT + "/" + image.filename;

    // 4. 存储文件
    if (!aod::FileUtil(video_path).SetContent(video.content)) {
        res.status = 500;
        res.set_content(R"({"result":false,"reason":"视频存储失败"})", "application/json");
        return;
    }

    if (!aod::FileUtil(image_path).SetContent(image.content)) {
        res.status = 500;
        res.set_content(R"({"result":false,"reason":"图片存储失败"})", "application/json");
        return;
    }

    // 5. 写入数据库
    Json::Value video_json;
    video_json["name"] = name.content;
    video_json["info"] = info.content;
    video_json["video"] = std::string(VIDEO_ROOT) + "/" + video.filename;
    video_json["image"] = std::string(IMAGE_ROOT) + "/" + image.filename;

    if (!tbv->Insert(video_json)) {
        res.status = 500;
        res.set_content(R"({"result":false,"reason":"数据库写入失败"})", "application/json");
        return;
    }

    // 6. 成功响应
    res.set_content(R"({"result":true,"reason":"上传成功"})", "application/json");
    res.set_header("Content-Type","application/json");
    return;
}

void aod::Server::Delete(const httplib::Request& req, httplib::Response& res) {
    std::cout << "调用Delete函数" << std::endl;

    //获取要删除的视频ID
    int video_id = std::stoi(req.matches[1].str());
    //删除视频以及图片
    Json::Value video;
    if(tbv->SelectOne(video_id,&video) == false)
    {
        res.status = 500;
        res.set_content(R"({"result":false,"reason":"不存在视频信息"})", "application/json");
        return;
    }
    std::string www_root = WWWROOT;
    std::string video_path = www_root + video["video"].asCString();
    std::string image_path = www_root + video["image"].asCString();

    //删除数据库数据
    if(tbv->Delete(video_id) == false)
    {
        res.status = 500;
        res.set_content(R"({"result":false,"reason":"删除数据库数据失败"})", "application/json");
        return;
    }

    //成功响应
    res.set_content(R"({"result":true,"reason":"删除成功"})", "application/json");
    res.set_header("Content-Type","application/json");
    return;
}

void aod::Server::Update(const httplib::Request& req, httplib::Response& res) {
    std::cout << "调用Update函数" << std::endl;

    //获取要更新的视频ID
    int video_id = std::stoi(req.matches[1].str());
    Json::Value video;
    if(aod::JsonUtil::UnSerialize(req.body,&video) == false)
    {
        res.status = 400;
        res.set_content(R"({"result":false,"reason":"反序列化失败,数据格式错误"})", "application/json");
        return;
    }

    if(tbv->UpDate(video_id,video) == false)
    {
        res.status = 500;
        res.set_content(R"({"result":false,"reason":"更新数据库数据失败"})", "application/json");
        return;
    }

    //成功响应
    res.set_content(R"({"result":true,"reason":"更新成功"})", "application/json");
    res.set_header("Content-Type","application/json");
    return;
}

void aod::Server::SelectOne(const httplib::Request& req, httplib::Response& res) {
    std::cout << "调用SelectOne函数" << std::endl;
    
    //获取要查询的视频ID
    int video_id = std::stoi(req.matches[1].str());
    Json::Value video;
    if(tbv->SelectOne(video_id,&video) == false)
    {
        res.status = 500;
        res.set_content(R"({"result":false,"reason":"查询数据库单个数据失败"})", "application/json");
        return;
    }
    //查询成功，响应正文
    aod::JsonUtil::Serialize(video,&res.body);
    res.set_header("Content-Type","application/json");
    return;
}

void aod::Server::SelectAll(const httplib::Request& req, httplib::Response& res) {
    //  /video    /video?search="关键字"'
    //设置查询信号：默认全部为true  模糊为false
    bool select_flag = true;
    std::string select_key;
    if(req.has_param("search") == true)
    {
        select_flag = false;//设置为模糊匹配信号
        select_key = req.get_param_value("search");
    }
    if(req.has_param("search") == true) std::cout << "调用SelectLike函数" << std::endl;
    else std::cout << "调用Select函数" << std::endl;
    Json::Value videos;
    if(select_flag == true)
    {
        if(tbv->SelectAll(&videos) == false)
        {
            res.status = 500;
            res.set_content(R"({"result":false,"reason":"查询数据库所有数据失败"})", "application/json");
            res.set_header("Content-Type","application/json");
            return;
        }
    }
    else    //模糊匹配
    {
        if(tbv->SelectLike(select_key,&videos) == false)
        {
            res.status = 500;
            res.set_content(R"({"result":false,"reason":"查询数据库对应 关键字数据失败"})", "application/json");
            res.set_header("Content-Type","application/json");
            return;
        }
    }

    //查询成功，响应正文
    aod::JsonUtil::Serialize(videos,&res.body);
    res.set_header("Content-Type","application/json");
    return;
}

// 用户注册
void aod::Server::UserRegister(const httplib::Request& req, httplib::Response& res) {
    std::cout << "调用UserRegister函数" << std::endl;
    
    Json::Value user_data;
    if (!aod::JsonUtil::UnSerialize(req.body, &user_data)) {
        res.status = 400;
        res.set_content(R"({"result":false,"reason":"数据格式错误"})", "application/json");
        return;
    }
    
    // 检查必需字段
    if (!user_data.isMember("username") || !user_data.isMember("password") || !user_data.isMember("email")) {
        res.status = 400;
        res.set_content(R"({"result":false,"reason":"缺少必需字段"})", "application/json");
        return;
    }
    
    std::string username = user_data["username"].asString();
    std::string password = user_data["password"].asString();
    std::string email = user_data["email"].asString();
    
    if (tbu->Register(username, password, email)) {
        res.status = 201;
        res.set_content(R"({"result":true,"reason":"注册成功"})", "application/json");
    } else {
        res.status = 409;
        res.set_content(R"({"result":false,"reason":"用户名或邮箱已存在"})", "application/json");
    }
    
    res.set_header("Content-Type", "application/json");
}

// 用户登录
void aod::Server::UserLogin(const httplib::Request& req, httplib::Response& res) {
    std::cout << "调用UserLogin函数" << std::endl;
    
    Json::Value login_data;
    if (!aod::JsonUtil::UnSerialize(req.body, &login_data)) {
        res.status = 400;
        res.set_content(R"({"result":false,"reason":"数据格式错误"})", "application/json");
        return;
    }
    
    if (!login_data.isMember("username") || !login_data.isMember("password")) {
        res.status = 400;
        res.set_content(R"({"result":false,"reason":"缺少用户名或密码"})", "application/json");
        return;
    }
    
    std::string username = login_data["username"].asString();
    std::string password = login_data["password"].asString();
    
    Json::Value user_info;
    if (tbu->Login(username, password, &user_info)) {
        std::string session_id, expires_at;
        int user_id = user_info["user_id"].asInt();
        
        if (_session_table.CreateSession(user_id, &session_id, &expires_at)) {
            Json::Value response;
            response["result"] = true;
            response["session_id"] = session_id;
            response["expires_at"] = expires_at;
            response["user_info"] = user_info;
            
            _auth.SetAuthHeaders(res, session_id);
            
            std::string response_body;
            aod::JsonUtil::Serialize(response, &response_body);
            res.set_content(response_body, "application/json");
        } else {
            res.status = 500;
            res.set_content(R"({"result":false,"reason":"创建会话失败"})", "application/json");
        }
    } else {
        res.status = 401;
        res.set_content(R"({"result":false,"reason":"用户名或密码错误"})", "application/json");
    }
    
    res.set_header("Content-Type", "application/json");
}

// 用户登出
void aod::Server::UserLogout(const httplib::Request& req, httplib::Response& res) {
    std::cout << "调用UserLogout函数" << std::endl;
    
    Json::Value user_info;
    if (!RequireAuth(req, res, _auth, &user_info)) {
        return;
    }
    
    std::string session_id = _auth.ExtractSessionId(req);
    if (!session_id.empty()) {
        _session_table.DeleteSession(session_id);
    }
    
    res.status = 204;
    res.set_header("Set-Cookie", "session_id=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/");
}

// 刷新会话
void aod::Server::UserRefreshSession(const httplib::Request& req, httplib::Response& res) {
    std::cout << "调用UserRefreshSession函数" << std::endl;
    
    Json::Value user_info;
    if (!RequireAuth(req, res, _auth, &user_info)) {
        return;
    }
    
    std::string session_id = _auth.ExtractSessionId(req);
    std::string new_expires_at;
    
    if (_session_table.RefreshSession(session_id, &new_expires_at)) {
        Json::Value response;
        response["result"] = true;
        response["session_id"] = session_id;
        response["expires_at"] = new_expires_at;
        
        std::string response_body;
        aod::JsonUtil::Serialize(response, &response_body);
        res.set_content(response_body, "application/json");
    } else {
        res.status = 500;
        res.set_content(R"({"result":false,"reason":"刷新会话失败"})", "application/json");
    }
    
    res.set_header("Content-Type", "application/json");
}

// 获取用户信息
void aod::Server::GetUserInfo(const httplib::Request& req, httplib::Response& res) {
    std::cout << "调用GetUserInfo函数" << std::endl;
    
    Json::Value user_info;
    if (!RequireAuth(req, res, _auth, &user_info)) {
        return;
    }
    
    int requested_user_id = std::stoi(req.matches[1].str());
    int current_user_id = user_info["user_id"].asInt();
    
    // 用户只能查看自己的信息，除非是管理员
    if (requested_user_id != current_user_id && !_auth.IsAdmin(user_info)) {
        _auth.SetForbiddenResponse(res);
        return;
    }
    
    Json::Value requested_user_info;
    if (tbu->GetUserById(requested_user_id, &requested_user_info)) {
        std::string response_body;
        aod::JsonUtil::Serialize(requested_user_info, &response_body);
        res.set_content(response_body, "application/json");
    } else {
        res.status = 404;
        res.set_content(R"({"result":false,"reason":"用户不存在"})", "application/json");
    }
    
    res.set_header("Content-Type", "application/json");
}

// 更新用户信息
void aod::Server::UpdateUserInfo(const httplib::Request& req, httplib::Response& res) {
    std::cout << "调用UpdateUserInfo函数" << std::endl;
    
    Json::Value user_info;
    if (!RequireAuth(req, res, _auth, &user_info)) {
        return;
    }
    
    int requested_user_id = std::stoi(req.matches[1].str());
    int current_user_id = user_info["user_id"].asInt();
    
    // 用户只能更新自己的信息，除非是管理员
    if (requested_user_id != current_user_id && !_auth.IsAdmin(user_info)) {
        _auth.SetForbiddenResponse(res);
        return;
    }
    
    Json::Value update_data;
    if (!aod::JsonUtil::UnSerialize(req.body, &update_data)) {
        res.status = 400;
        res.set_content(R"({"result":false,"reason":"数据格式错误"})", "application/json");
        return;
    }
    
    if (tbu->UpdateUser(requested_user_id, update_data)) {
        res.set_content(R"({"result":true,"reason":"更新成功"})", "application/json");
    } else {
        res.status = 500;
        res.set_content(R"({"result":false,"reason":"更新失败"})", "application/json");
    }
    
    res.set_header("Content-Type", "application/json");
}

// 点赞视频
void aod::Server::LikeVideo(const httplib::Request& req, httplib::Response& res) {
    std::cout << "调用LikeVideo函数" << std::endl;
    
    Json::Value user_info;
    if (!RequireAuth(req, res, _auth, &user_info)) {
        return;
    }
    
    int video_id = std::stoi(req.matches[1].str());
    int user_id = user_info["user_id"].asInt();
    
    // 获取当前点赞状态
    bool current_liked;
    int like_count;
    if (!tbvl->GetLikeStatus(video_id, user_id, &current_liked, &like_count)) {
        res.status = 500;
        res.set_content(R"({"result":false,"reason":"获取点赞状态失败"})", "application/json");
        return;
    }
    
    // 切换点赞状态
    bool new_liked = !current_liked;
    if (tbvl->LikeVideo(video_id, user_id, new_liked)) {
        // 重新获取点赞数
        tbvl->GetLikeStatus(video_id, user_id, &new_liked, &like_count);
        
        Json::Value response;
        response["result"] = true;
        response["liked"] = new_liked;
        response["count"] = like_count;
        
        std::string response_body;
        aod::JsonUtil::Serialize(response, &response_body);
        res.set_content(response_body, "application/json");
    } else {
        res.status = 500;
        res.set_content(R"({"result":false,"reason":"点赞操作失败"})", "application/json");
    }
    
    res.set_header("Content-Type", "application/json");
}

// 获取视频点赞状态
void aod::Server::GetVideoLikeStatus(const httplib::Request& req, httplib::Response& res) {
    std::cout << "调用GetVideoLikeStatus函数" << std::endl;
    
    int video_id = std::stoi(req.matches[1].str());
    
    Json::Value user_info;
    bool liked = false;
    int like_count = 0;
    
    // 检查用户是否已登录（不强制要求登录）
    std::string session_id = _auth.ExtractSessionId(req);
    if (!session_id.empty() && _session_table.ValidateSession(session_id, &user_info)) {
        // 用户已登录，获取用户的点赞状态
        int user_id = user_info["user_id"].asInt();
        tbvl->GetLikeStatus(video_id, user_id, &liked, &like_count);
    } else {
        // 用户未登录，只返回总点赞数
        tbvl->GetVideoLikeCount(video_id, &like_count);
    }
    
    Json::Value response;
    response["result"] = true;
    response["liked"] = liked;
    response["count"] = like_count;
    
    std::string response_body;
    aod::JsonUtil::Serialize(response, &response_body);
    res.set_content(response_body, "application/json");
    res.set_header("Content-Type", "application/json");
}



